#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "../include/environ.h"
#include <sys/types.h>
#include <pwd.h>
#include <string.h>

int nbVar = 0;
int size = DEFAULT_ALLOC_INCR;
char **Environ = NULL;

//crée une ligne d'environ
char* createLine(const char *var, const char* valeur) {
    char* line = (char*) malloc(sizeof(char)*(strlen(var) + 2 + strlen(valeur)));
    strcpy(line, var);
    strcat(line, "=");
    strcat(line, valeur);
    return line;
}


//initialise environ avec les variables par défaut
void init_environ() {
    nbVar = 0;
    Environ = (char**) malloc(sizeof(char*)*DEFAULT_ALLOC_INCR);
    set_environ("HOME", (getpwuid(getuid()))->pw_dir);
    set_environ("PATH", "/bin:/usr/bin:/usr/local/bin");
    set_environ("IFS", " \t\n");
    set_environ("PROMPT", "polysh$ ");
    set_environ("TERM", "xterm");
    set_environ("PWD", (const char*)get_current_dir_name());
    set_environ("SHELL", "polysh 0.4");
}

void  set_environ(const char *var, const char *valeur) {
    if(Environ == NULL) {
       init_environ();
    }
    int i=0;
    //si ça existe je redéfinit
    while(i < nbVar){
      if(strncmp(var, Environ[i], strlen(var)) == 0){
        free(Environ[i]);
        Environ[i] = createLine(var, valeur);
        return;
      }
      ++i;
    }
    
    if(i >= nbVar) { // Ajout de variables
        Environ[i] = createLine(var, valeur); 
        ++nbVar;
    }
    // si pas assez de place j'ajoute une place
    if (size < nbVar)
    {
        size = size + DEFAULT_ALLOC_INCR;
        Environ = realloc(Environ, (size * sizeof(char *)));
    }

}

// retourne la valeur d'une variable d'environ
char *get_environ(const char *s) {
    if(!Environ) {
       init_environ();
    }
    int i = 0;
    while(i < nbVar) {
        if(strncmp(Environ[i], s, strlen(s)) == 0) {
            char* retour = Environ[i] + strlen(s) + 1;
            return retour;
        }
        ++i;
    }
    return NULL;
}

//Impression de l 'environnement sur le fichier f
void print_environ(FILE *f) {
    if(Environ == NULL) {
       init_environ();
    }
    int i = 0;
    while(i < nbVar) {
        fprintf(f, "%s\n", Environ[i++]);
    }
}


/* Ajouter les paramètres (dans argv) à l'environnement. De plus, 
 *  construire, la variable spéciale  "$#"  */
void add_program_parameters_environ(int argc, char *argv[]) {
    if(Environ == NULL) {
       init_environ();
    }
    int i = 1;
    char str[32];
    str[1] = '\0';
    char line[300];
    strcpy(line, "\0");
    while(i < argc) {
        if(i > 1) {
           strcat(line, " "); 
        }
        strcat(line, argv[i]);
        sprintf(str, "%d", i);
        char* arg = (char*)malloc(sizeof(char)*(strlen(argv[i]) +1));
        strcpy(arg, "\0");
        strcat(arg, "$");
        set_environ((const char*)strcat(arg, str), (const char*)argv[i]);
        free(arg);
        ++i;
    }
    int nbarg = argc-1;
    // $* : liste les arguments
    set_environ("$*", line);
    // $# :  nbr d'arguments
    sprintf(str, "%d", nbarg);
    set_environ("$#", str);
}


